import { EditOutlined } from '@ant-design/icons';
import type { ProFormInstance } from '@ant-design/pro-form';
import ProForm, { ModalForm, ProFormText } from '@ant-design/pro-form';
import { Descriptions, message, Spin } from 'antd';
import type { DescriptionsProps } from 'antd/lib/descriptions';
import React, { useEffect, useRef, useState } from 'react';

export interface DetailData<T> {
  success?: boolean;
  data?: T;
}

export interface ProDescriptionsItemProps<T = unknown> {
  label: string;
  span?: number;
  dataIndex: string;
  render?: (value: React.ReactNode, record: T) => React.ReactNode;
  editable?: boolean;
  onEdit?: (item: ProDescriptionsItemProps<T>) => boolean;
  renderEdit?: (
    item: ProDescriptionsItemProps<T>,
    config: {
      value?: any;
      record: T;
      onChange?: (value: any) => void;
    },
  ) => JSX.Element;
  onSubmit?: (value: any) => Promise<boolean | void>;
  onCancel?: () => void;
  afterClose?: () => void;
}

export interface ProDetailProps<T, U extends Record<string, any>> extends DescriptionsProps {
  // 详情信息的id
  params?: U;
  // 获取数据的请求
  request?: (params?: U) => Promise<DetailData<T>>;
  // 如何展示数据
  columns: ProDescriptionsItemProps<T>[];
  initData?: T;
  dataLoading?: boolean;
}

interface EditDomParams {
  value?: any;
  record: any;
  onChange?: any;
  item: ProDescriptionsItemProps<any> | undefined;
}

const EditDom: React.FC<EditDomParams> = (props): JSX.Element => {
  const { item, value, record, onChange } = props;

  if (!item) {
    return <div />;
  }

  if (item.renderEdit) {
    return (
      <ProForm.Item name={item.dataIndex} label={item.label}>
        {item.renderEdit(item, { value, record, onChange })}
      </ProForm.Item>
    );
  }

  return <ProFormText name={item.dataIndex} label={item.label} />;
};

const ProDescriptions: <T, U>(props: ProDetailProps<T, U>) => JSX.Element = (props) => {
  const { params, request, columns, initData, ...restProps } = props;

  const [data, setData] = useState<any>(props.initData);
  const [currentItem, setCurrentItem] = useState<ProDescriptionsItemProps<any>>();
  const [visibleEdit, setVisibleEdit] = useState<boolean>(false);
  // const [_, setConfirmLoading] = useState<boolean>(false);
  const [dataLoading, setDataLoading] = useState<boolean>(props.dataLoading || false);

  const formRef = useRef<ProFormInstance>();

  useEffect(() => {
    if (!request) {
      setDataLoading(props.dataLoading || false);
      if (initData) {
        setData(initData);
      }
      return;
    }
    setDataLoading(true);
    request(params).then((res) => {
      if (res && res.success === true && res.data) {
        setData(res.data);
        setDataLoading(false);
      }
    });
  }, [props.initData]);

  return (
    <Spin spinning={dataLoading}>
      <Descriptions {...restProps} column={restProps.column || 1}>
        {columns.map((item) => (
          <Descriptions.Item
            key={item.dataIndex}
            label={
              <span style={{ color: '#1890ff' }}>
                {item.label}
                {item.editable && item.onSubmit && (
                  <EditOutlined
                    onClick={() => {
                      formRef.current?.setFieldsValue({ [item.dataIndex]: data[item.dataIndex] });
                      setVisibleEdit(true);
                      setCurrentItem(columns.find((_item) => _item.dataIndex === item.dataIndex));
                    }}
                  />
                )}
              </span>
            }
          >
            {item.render ? item.render(data?.[item.dataIndex], data) : data?.[item.dataIndex]}{' '}
          </Descriptions.Item>
        ))}
      </Descriptions>

      <ModalForm
        layout={'vertical'}
        title={currentItem?.label}
        visible={visibleEdit}
        width={500}
        formRef={formRef}
        onVisibleChange={(visible) => {
          if (!visible) {
            setVisibleEdit(false);
            if (currentItem?.onCancel) {
              currentItem.onCancel();
            }
            setCurrentItem(undefined);
          }
        }}
        onFinish={async (formData) => {
          if (currentItem?.onSubmit) {
            const result = await currentItem.onSubmit(formData[currentItem.dataIndex]);

            if (result) {
              message.success('修改成功');
              setData({ ...data, ...formData });
            } else {
              await message.error('修改失败');
            }
            return true;
          } else {
            return false;
          }
        }}
      >
        <EditDom
          record={data}
          item={currentItem}
          onChange={(value: any) => {
            debugger;
            if (value) {
              const map = {};
              if (currentItem?.dataIndex) {
                map[currentItem?.dataIndex] = value;
              }
              formRef.current?.setFieldsValue(map);
            }
          }}
        />
      </ModalForm>
    </Spin>
  );
};

export default ProDescriptions;
